﻿namespace Leetcode.N0297;

public class Codec
{

    // Encodes a tree to a single string.
    public string serialize(TreeNode root)
    {
        if (root == null)
        {
            return "[]";
        }

        var queue = new System.Collections.Generic.Queue<TreeNode>();
        var sb = new System.Text.StringBuilder();
        sb.Append('[');
        if (root != null)
        {
            queue.Enqueue(root);
            sb.Append(root.val);
        }

        while (queue.Count > 0)
        {
            var list = new System.Collections.Generic.List<TreeNode>();
            while (queue.Count > 0)
            {
                var n = queue.Dequeue();
                list.Add(n);
            }

            foreach (var node in list)
            {
                sb.Append(',');
                if (node == null)
                {
                    sb.Append("null");
                    continue;
                }
                else
                {
                    if (node.left == null)
                    {
                        sb.Append("null");
                    }
                    else
                    {
                        sb.Append(node.left.val);
                        queue.Enqueue(node.left);
                    }

                    sb.Append(',');
                    if (node.right == null)
                    {
                        sb.Append("null");
                    }

                    else
                    {
                        sb.Append(node.right.val);
                        queue.Enqueue(node.right);
                    }
                }
            }
        }

        return this.TrimEndNull(sb.ToString()) + ']';
    }

    private string TrimEndNull(string value)
    {
        int length = value.Length - 1;
        for (var i = value.Length - 1; i >= 0; i -= 5)
        {
            if (value[i] == 'l')
            {
                continue;
            }
            length = i + 1;
            break;

        }
        return value.Substring(0, length);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(string data)
    {
        var sItems = data.Trim(new char[] { '[', ']' }).Split(',', StringSplitOptions.RemoveEmptyEntries);
        var values = new int?[sItems.Length];
        if (values.Length == 0)
        {
            return null;
        }

        for (int i = 0; i < sItems.Length; i++)
        {
            var s = sItems[i].Trim();
            values[i] = s == "null" ? (int?)null : int.Parse(s);
        }

        var root = new TreeNode(values[0].Value);
        var queue = new System.Collections.Generic.Queue<TreeNode>();
        queue.Enqueue(root);
        int index = 0;
        while (queue.Count > 0)
        {
            var nodes = new TreeNode[queue.Count];
            var i = 0;
            while (queue.Count > 0)
            {
                var node = queue.Dequeue();
                nodes[i++] = node;

                if (index < values.Length - 1)
                {
                    var left = values[++index];
                    if (left != null)
                    {
                        node.left = new TreeNode(left.Value);
                    }
                }

                if (index < values.Length - 1)
                {
                    var right = values[++index];
                    if (right != null)
                    {
                        node.right = new TreeNode(right.Value);
                    }
                }
            }

            foreach (var item in nodes)
            {
                if (item.left != null)
                {
                    queue.Enqueue(item.left);
                }
                if (item.right != null)
                {
                    queue.Enqueue(item.right);
                }
            }
        }

        return root;
    }
}
